﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Walson.IO;

namespace Walson.Net.Sockets
{
    /// <summary>
    /// 简化的 UDP Client 类
    /// </summary>
    public class UdpClientCompact : IDisposable
    {
        /// <summary>
        /// 模式
        /// </summary>
        public enum Modes
        {
            /// <summary>
            /// 流模式，可按流的方式对组件进行读写操作
            /// </summary>
            Stream,
            /// <summary>
            /// 消息模式，按 UDP 包的方式对组件进行读写操作
            /// </summary>
            Packet
        }

        #region 属性
        private Modes _Mode = Modes.Packet;
        /// <summary>
        /// 工作模式
        /// </summary>
        public Modes Mode
        {
            get
            {
                return _Mode;
            }
            set
            {
                if (IsRunning)
                {
                    throw (new Exception("请先停止组件再进行设置"));
                }
                _Mode = value;
            }
        }

        /// <summary>
        /// 指示组件是否正在运行
        /// </summary>
        public bool IsRunning
        {
            get;
            private set;
        }

        private string _Address = string.Empty;
        /// <summary>
        /// 本机 IP 地址
        /// </summary>
        public string Address
        {
            get
            {
                return _Address;
            }
            set
            {
                if (IsRunning)
                    throw (new Exception("组件正在运行。请停止组件后再进行设置。"));
                _Address = value;
            }
        }

        private int _Port = 0;
        /// <summary>
        /// 本机端口号
        /// </summary>
        public int Port
        {
            get
            {
                return _Port;
            }
            set
            {
                if (IsRunning)
                    throw (new Exception("组件正在运行。请停止组件后再进行设置。"));
                _Port = value;
            }
        }

        private int _ReceiveBufferSize = 10240;
        /// <summary>
        /// 设置接收缓冲区大小
        /// </summary>
        public int ReceiveBufferSize
        {
            get
            {
                return _Client.ReceiveBufferSize;
            }
            set
            {
                _ReceiveBufferSize = value;
                if (_Client != null && _Client.ReceiveBufferSize != value)
                {
                    _Client.ReceiveBufferSize = value;
                }
            }
        }

        private int _SendBufferSize = 10240;
        /// <summary>
        /// 设置发送缓冲区大小
        /// </summary>
        public int SendBufferSize
        {
            get
            {
                return _Client.SendBufferSize;
            }
            set
            {
                SendBufferSize = value;
                if (_Client != null && _Client.SendBufferSize != value)
                {
                    _Client.SendBufferSize = value;
                }
            }
        }

        private int _BytesAvailable = 0;
        /// <summary>
        /// 获取从网络接收的可读取的数据量（流模式）
        /// </summary>
        public int BytesAvailable
        {
            get
            {
                return _BytesAvailable;
            }
        }

        /// <summary>
        /// 可供读取的数据包数量（包模式）
        /// </summary>
        public int PacketsAvailable
        {
            get
            {
                int n = -1;
                lock (_InternalMessageQueue)
                {
                    n = _InternalMessageQueue.Count;
                }
                return n;
            }
        }

        /// <summary>
        /// 远端主机的数量（流模式）
        /// </summary>
        public int EndPointCount
        {
            get
            {
                if (_InternalStreams == null)
                    return 0;
                else
                    return _InternalStreams.Keys.Count;
            }
        }
        /// <summary>
        /// 来自远端主机数据流的超时时间（秒）。当超过指定时间没有从远程主机接收到数据、或没有向远程主机写入数据，
        /// 则将触发超时事件，并将该流从缓存中删除。尚未读取的数据将会丢失。
        /// </summary>
        public int RemoteStreamTimeout
        {
            get; set;
        }

        #endregion


        #region 事件
        /// <summary>
        /// 事件到达处理方法
        /// </summary>
        /// <param name="sender">事件的发送方</param>
        /// <param name="e">参数</param>
        public delegate void DataReceivedHandler(UdpClientCompact sender, IPEndPoint endPoint);
        /// <summary>
        /// 数据到达事件
        /// </summary>
        public event DataReceivedHandler DataReceived;

        /// <summary>
        /// 网络数据流读取超时处理方法
        /// </summary>
        /// <param name="sender"></param>
        public delegate void RemoteStreamTimeoutHandler(object sender);
        /// <summary>
        /// 网络数据流读取超时
        /// </summary>
        public event RemoteStreamTimeoutHandler RemoteStreamTimeoutOccured;
        #endregion



        #region 变量

        private Socket _Client;
        private Queue<Packet> _InternalMessageQueue;
        bool _CleanedUp = true;
        bool _TerminateReciever;
        Dictionary<IPEndPoint, TimedBinaryStream> _InternalStreams;
        #endregion




        private void FreeResources()
        {
            if (this._CleanedUp == false)
            {
                if (_InternalMessageQueue != null)
                {
                    _InternalMessageQueue.Clear();
                    _InternalMessageQueue = null;
                }

                if (_InternalStreams != null)
                {
                    foreach (IPEndPoint ep in _InternalStreams.Keys)
                    {
                        _InternalStreams[ep].Dispose();
                        //_InternalStreams[ep] = null;
                    }
                    _InternalStreams.Clear();
                    _InternalStreams = null;
                }

                if (_Client != null)
                {
                    if (_Client.Connected)
                    {
                        _Client.Disconnect(true);
                    }
                    _Client.Close();
                    _Client.Dispose();
                    _Client = null;
                }
                this._CleanedUp = true;
            }
        }

        /// <summary>
        /// 获取本机所有网卡
        /// </summary>
        /// <returns>所有网卡</returns>
        public static NetworkInterface[] GetAllPysicalAdapers()
        {
            NetworkInterface[] fNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
            List<NetworkInterface> result = new List<NetworkInterface>();
            foreach (NetworkInterface adapter in fNetworkInterfaces)
            {
                //string fCardType = "未知网卡";
                string fRegistryKey = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\" + adapter.Id + "\\Connection";
                RegistryKey rk = Registry.LocalMachine.OpenSubKey(fRegistryKey, false);
                if (rk != null)
                {
                    // 区分 PnpInstanceID    
                    // 如果前面有 PCI 就是本机的真实网卡   
                    // MediaSubType 为 01 则是常见网卡，02为无线网卡。   
                    string fPnpInstanceID = rk.GetValue("PnpInstanceID", "").ToString();
                    int fMediaSubType = Convert.ToInt32(rk.GetValue("MediaSubType", 0));
                    if (fPnpInstanceID.Length > 3 && fPnpInstanceID.Substring(0, 3) == "PCI")
                    {
                        //fCardType = "物理网卡";
                        result.Add(adapter);
                    }
                    else if (fMediaSubType == 1)
                    {
                        //fCardType = "虚拟网卡";
                    }
                    else if (fMediaSubType == 2)
                    {
                        //fCardType = "无线网卡";
                        result.Add(adapter);
                    }
                }
            }
            return result.ToArray();
        }






















        /// <summary>
        /// 初始化 UdpClientCompact 类的新实例，并将它绑定到所提供的本地 IP 地址和端口号。
        /// </summary>
        /// <param name="ipAddress">本地 IP 地址</param>
        /// <param name="port">本地端口号</param>
        /// /// <param name="timeout">超时时间</param>
        public UdpClientCompact(string ipAddress = "127.0.0.1", int port = 9000, int timeout = 5)
        {
            _Address = ipAddress;
            _Port = port;

            RemoteStreamTimeout = timeout;
        }

        /// <summary>
        /// 初始化 UdpClientCompact 类的新实例，并将它绑定到所提供的本地 IP 地址和端口号。
        /// </summary>
        public UdpClientCompact()
            : this("127.0.0.1", 9000, 5)
        {

        }

        public UdpClientCompact(IPAddress ipAddress, int port=9000,int timeout=5)
        {
            _Address = ipAddress.ToString();
            _Port = port;

            RemoteStreamTimeout = timeout;
        }

        /// <summary>
        /// 启动 UDP 收发器
        /// </summary>
        /// <returns>是否启动成功</returns>
        public bool Start()
        {
            bool result = false;
            if(IsRunning)
            {
                return result;
            }

            this._CleanedUp = false;
            _BytesAvailable = 0;
            

            IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(_Address), _Port);

            _Client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            _Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            _Client.EnableBroadcast = true;
            _Client.ReceiveBufferSize = _ReceiveBufferSize;
            _Client.SendBufferSize = _SendBufferSize;
            _Client.Bind(localEP);

            _TerminateReciever = false;

            Thread thd;
            if (Mode == Modes.Packet)
            {
                _InternalMessageQueue = new Queue<Packet>();
                thd = new Thread(new ThreadStart(thdDoMessageReceive));

            }
            else
            {
                _InternalStreams = new Dictionary<IPEndPoint, TimedBinaryStream>();
                thd = new Thread(new ThreadStart(thdDoStreamReceive));
            }
            thd.IsBackground = true;
            thd.Start();
            
            result = true;

            return result;
        }

        /// <summary>
        /// 停止组件运行
        /// </summary>
        public void Stop()
        {
            if (IsRunning == true)
            {
                _TerminateReciever = true;

                Action act = new Action(() => 
                {
                    while(IsRunning)
                    {
                        Thread.Sleep(10);
                    }
                    FreeResources();
                    _BytesAvailable = 0;
                });
                act.BeginInvoke(null, null);
            }
        }



        /// <summary>
        /// 从缓冲区中读取消息
        /// </summary>
        /// <returns>读取的消息</returns>
        public Packet ReadPacket()
        {
            Packet msg;
            lock (_InternalMessageQueue)
            {
                if (_InternalMessageQueue.Count == 0)
                    msg = null;
                else
                    msg = _InternalMessageQueue.Dequeue();
            }
            return msg;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取数据
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <param name="buffer">数据将要读到的缓冲区字节数组</param>
        /// <param name="offset">buffer 中的偏移量</param>
        /// <param name="count">要读取的长度</param>
        /// <returns>实际读取的字节数</returns>
        public int Read(IPEndPoint ipe, byte[] buffer, int offset, int count)
        {
            if (_InternalStreams.ContainsKey(ipe) == false)
            {
                throw new ArgumentOutOfRangeException();
            }

            if (buffer == null)
            {
                throw new NullReferenceException();
            }

            if (buffer.Length == 0)
            {
                return 0;
            }

            if (offset > buffer.Length || offset < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            if (count > buffer.Length || count < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            if (offset + count > buffer.Length)
            {
                throw new ArgumentOutOfRangeException();
            }

            if (offset == 0)
            {
                lock (_InternalStreams)
                {
                    if (count > _InternalStreams[ipe].Length)
                    {
                        _BytesAvailable -= (int)_InternalStreams[ipe].Length;
                    }
                    else
                    {
                        _BytesAvailable -= count;
                    }
                    return _InternalStreams[ipe].Read(buffer, count);
                }

            }
            else
            {
                byte[] buf = new byte[count];
                lock (_InternalStreams)
                {
                    if (count > _InternalStreams[ipe].Length)
                    {
                        _BytesAvailable -= (int)_InternalStreams[ipe].Length;
                    }
                    else
                    {
                        _BytesAvailable -= count;
                    }

                    int n = _InternalStreams[ipe].Read(buf, count);
                    Array.Copy(buf, 0, buffer, offset, n);
                    return n;
                }
            }
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 字节
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的字节</returns>
        public byte ReadByte(IPEndPoint ipe)
        {
            byte b;
            lock (_InternalStreams)
            {
                b = _InternalStreams[ipe].ReadByte();
                _BytesAvailable--;
            }
            return b;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取多个字节
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <param name="count">要读取的字节数</param>
        /// <returns>读取的字节数组</returns>
        public byte[] ReadBytes(IPEndPoint ipe, int count)
        {
            lock (_InternalStreams)
            {
                if (count > _InternalStreams[ipe].Length)
                {
                    _BytesAvailable -= (int)_InternalStreams[ipe].Length;
                }
                else
                {
                    _BytesAvailable -= count;
                }
                return _InternalStreams[ipe].ReadBytes(count);
            }
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 16 位无符号整数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 16 位无符号整数</returns>
        public UInt16 ReadUInt16(IPEndPoint ipe)
        {
            UInt16 value = _InternalStreams[ipe].ReadUInt16();
            _BytesAvailable -= sizeof(UInt16);
            return value;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 32 位无符号整数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 32 位无符号整数</returns>
        public UInt32 ReadUInt32(IPEndPoint ipe)
        {
            UInt32 value = _InternalStreams[ipe].ReadUInt32();
            _BytesAvailable -= sizeof(UInt32);
            return value;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 64 位无符号整数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 64 位无符号整数</returns>
        public UInt64 ReadUInt64(IPEndPoint ipe)
        {
            UInt64 value = _InternalStreams[ipe].ReadUInt64();
            _BytesAvailable -= sizeof(UInt64);
            return value;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 8 位有符号整数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 8 位有符号整数</returns>
        public sbyte ReadSByte(IPEndPoint ipe)
        {
            sbyte b = _InternalStreams[ipe].ReadSbyte();
            _BytesAvailable--;
            return b;
        }
        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个字符
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 1 个字符</returns>
        public char ReadChar(IPEndPoint ipe)
        {
            char c = _InternalStreams[ipe].ReadChar();
            _BytesAvailable-=sizeof(char);
            return c;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取字符数组
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <param name="count">要读出的数量</param>
        /// <returns>读取的字符数组</returns>
        public char[] ReadChars(IPEndPoint ipe, int count)
        {
            if (count > _InternalStreams[ipe].Length)
            {
                _BytesAvailable -= (int)_InternalStreams[ipe].Length;
            }
            else
            {
                _BytesAvailable -= count;
            }
            return _InternalStreams[ipe].ReadChars(count);
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 16 位有符号整数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 16 位有符号整数</returns>
        public Int16 ReadInt16(IPEndPoint ipe)
        {
            Int16 value = _InternalStreams[ipe].ReadInt16();
            _BytesAvailable -= sizeof(Int16);
            return value;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 32 位有符号整数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 32 位有符号整数</returns>
        public Int32 ReadInt32(IPEndPoint ipe)
        {
            Int32 value = _InternalStreams[ipe].ReadInt32();
            _BytesAvailable -= sizeof(Int32);
            return value;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 64 位有符号整数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的 64 位有符号整数</returns>
        public Int64 ReadInt64(IPEndPoint ipe)
        {
            Int64 value = _InternalStreams[ipe].ReadInt64();
            _BytesAvailable -= sizeof(Int64);
            return value;
        }

        /// <summary>
        /// 从来自指定终端的数据流中读取 1 个 双精度浮点数
        /// </summary>
        /// <param name="ipe">指定的终端</param>
        /// <returns>读取的浮点数</returns>
        public double ReadDouble(IPEndPoint ipe)
        {
            double value = _InternalStreams[ipe].ReadDouble();
            _BytesAvailable -= sizeof(double);
            return value;
        }


        /// <summary>
        /// 清除已接收的所有消息和数据
        /// </summary>
        public void Clear()
        {
            if (_Mode == Modes.Packet)
            {
                lock (_InternalMessageQueue)
                {
                    _InternalMessageQueue.Clear();

                    EndPoint any = new IPEndPoint(IPAddress.Any, 0);
                    byte[] buffer;
                    if (_Client.Available > 0)
                    {
                        buffer = new byte[_Client.Available];
                        _Client.ReceiveFrom(buffer, ref any);
                    }
                }
            }
            else
            {
                lock (_InternalStreams)
                {
                    foreach (IPEndPoint ipe in _InternalStreams.Keys)
                    {
                        _InternalStreams[ipe].Dispose();
                    }
                    _InternalStreams.Clear();
                }
            }

            GC.Collect();
        }

        /// <summary>
        /// 向指定主机发送 UDP 数据报。
        /// </summary>
        /// <param name="addr">目的主机的 IP 地址</param>
        /// <param name="port">目的主机的端口号</param>
        /// <param name="dgram">要发送的数据缓冲区</param>
        /// <param name="offset">数据缓冲区中从 0 开始计算的偏移量</param>
        /// <param name="size">要发送的数据长度</param>
        /// <returns></returns>
        public int SendTo(IPAddress addr, int port, byte[] dgram, int offset, int size)
        {
            if (_Client == null)
                return -1;

            IPEndPoint endPoint = new IPEndPoint(addr, port);
            return _Client.SendTo(dgram, offset, size, SocketFlags.None, endPoint);
        }

        /// <summary>
        /// 向指定主机发送 UDP 数据报。
        /// </summary>
        /// <param name="addr">目的主机的 IP 地址</param>
        /// <param name="port">目的主机的端口号</param>
        /// <param name="dgram">要发送的数据缓冲区</param>
        /// <returns></returns>
        public int SendTo(IPAddress addr, int port, byte[] dgram)
        {
            return SendTo(addr, port, dgram, 0, dgram.Length);
        }


//         /// <summary>
//         /// 向指定主机发送 UDP 数据报。
//         /// </summary>
//         /// <param name="ipAddress">远端主机 IP 地址</param>
//         /// <param name="port">远端主机端口号</param>
//         /// <param name="dgram">Byte 类型的数组，它指定您打算发送的 UDP 数据报，表示为字节数组。</param>
//         /// <param name="offset">缓冲区中开始发送数据的位置</param>
//         /// <param name="size">要发送的字节数</param>
//         /// <returns></returns>
//         public int SendTo(IPAddress ipAddress, int port, byte[] dgram, int offset, int size)
//         {
//             if (_Client == null)
//                 return -1;
// 
//             IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
//             return _Client.SendTo(dgram, offset, size, SocketFlags.None, endPoint);
//         }

        /// <summary>
        /// 向指定主机发送 UDP 数据报。
        /// </summary>
        /// <param name="ipAddress">远端主机 IP 地址</param>
        /// <param name="port">远端主机端口号</param>
        /// <param name="str">字符串类型的数据，它指定您打算作为 UDP 数据报发送的字符串。</param>
        /// <returns>已发送的字节数。</returns>
        public int SendTo(IPAddress ipAddress, int port, string str)
        {
            byte[] dgram = System.Text.Encoding.Default.GetBytes(str);
            return SendTo(ipAddress, port, dgram, 0, dgram.Length);
        }

        /// <summary>
        /// 向指定主机发送 UDP 数据报。
        /// </summary>
        /// <param name="ipAddress">远端主机 IP 地址</param>
        /// <param name="port">远端主机端口号</param>
        /// <param name="structOrClass">object 类型的数据，可以是一个结构或类，它指定您打算作为 UDP 数据报发送的内容，该内容将被自动转换为字节数组发送。</param>
        /// <returns>已发送的字节数。</returns>
        public int SendTo(IPAddress ipAddress, int port, object structOrClass)
        {
            byte[] dgram = Walson.Tools.Convert.ToBytes(structOrClass);
            return SendTo(ipAddress, port, dgram, 0, dgram.Length);
        }

        /// <summary>
        /// 向网络广播 UDP 数据报
        /// </summary>
        /// <param name="port">远端主机端口号</param>
        /// <param name="dgram">Byte 类型的数组，它指定您打算发送的 UDP 数据报，表示为字节数组。</param>
        /// <param name="offset">缓冲区中开始发送数据的位置。</param>
        /// <param name="size">数据报中的字节数。</param>
        /// <returns>已发送的字节数。</returns>
        public int Broadcast(int port, byte[] dgram, int offset, int size)
        {
            if (_Client == null)
                return -1;

            IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, port);
            return _Client.SendTo(dgram, offset, size, SocketFlags.None, endPoint);
        }

        /// <summary>
        /// 向网络广播 UDP 数据报
        /// </summary>
        /// <param name="port">远端主机端口号</param>
        /// <param name="dgram">Byte 类型的数组，它指定您打算发送的 UDP 数据报，表示为字节数组。</param>
        /// <returns>已发送的字节数。</returns>
        public int Broadcast(int port, byte[] dgram)
        {
            return Broadcast(port, dgram, 0, dgram.Length);
        }

        /// <summary>
        /// 向网络广播 UDP 数据报
        /// </summary>
        /// <param name="port">远端主机端口号</param>
        /// <param name="structOrClass">object 类型的数据，可以是一个结构或类，它指定您打算作为 UDP 数据报发送的内容，该内容将被自动转换为字节数组发送。</param>
        /// <returns>已发送的字节数。</returns>
        public int Broadcast(int port, object structOrClass)
        {
            byte[] dgram = Walson.Tools.Convert.ToBytes(structOrClass);
            return Broadcast(port, dgram);
        }
        


        private void thdDoStreamReceive()
        {
            EndPoint any = (EndPoint)(new IPEndPoint(IPAddress.Any, 0));
            IsRunning = true;
            int receivedByteCount = 0;
            int availableCount = 0;
            while (_TerminateReciever==false)
            {
                if (_Client.Available <= 0)
                {
                    Thread.Sleep(1);
                    continue;
                }

                availableCount = _Client.Available;
                if (availableCount == 0)
                {
                    Thread.Sleep(1);
                    continue;
                }

                byte[] buffer = new byte[availableCount];
                receivedByteCount = _Client.ReceiveFrom(buffer, ref any);
                lock (_InternalStreams)
                {
                    if (_InternalStreams.ContainsKey((IPEndPoint)any) == false)
                    {
                        IPEndPoint ipe = new IPEndPoint((any as IPEndPoint).Address, (any as IPEndPoint).Port);
                        TimedBinaryStream tbs = new TimedBinaryStream();
                        tbs.TimeOut = RemoteStreamTimeout;
                        tbs.StreamEmptyOccured += (sender) =>
                        {
                            IPEndPoint tempIpe = null;
                            bool found = false;   

                            foreach (IPEndPoint iipe in _InternalStreams.Keys)
                            {
                                if (_InternalStreams[iipe] == sender)
                                {
                                    tempIpe = iipe;
                                    found = true;
                                    break;
                                }
                            }
                            if (found)
                            {
                                RemoteStreamTimeoutOccured?.Invoke(_InternalStreams[tempIpe]);

                                _InternalStreams[tempIpe].Dispose();
                                _InternalStreams[tempIpe] = null;
                                _InternalStreams.Remove(tempIpe);
                            }
                        };
                        _InternalStreams.Add(ipe, tbs);
                    }
                    _InternalStreams[(IPEndPoint)any].Write(buffer, 0, receivedByteCount);
                    _BytesAvailable += receivedByteCount;
                }

                //DataReceived?.Invoke((IPEndPoint)any, new EventArgs());
                DataReceived?.Invoke(this, (IPEndPoint)any);
            }
            IsRunning = false;
        }

        private void thdDoMessageReceive()
        {
            EndPoint any = (EndPoint)(new IPEndPoint(IPAddress.Any, 0));
            int receivedByteCount = 0;
            int availableCount = 0;
            IsRunning = true;

            while (_TerminateReciever == false)
            {
                if (_Client.Available <= 0)
                {
                    Thread.Sleep(1);
                    continue;
                }

                availableCount = _Client.Available;
                if (availableCount == 0)
                {
                    Thread.Sleep(1);
                    continue;
                }

                try
                {                    
                    byte[] data = new byte[availableCount];
                    receivedByteCount = _Client.ReceiveFrom(data, ref any);
                    Packet packet = new Packet(((IPEndPoint)any).Address, ((IPEndPoint)any).Port, data, receivedByteCount);

                    lock (_InternalMessageQueue)
                    {
                        _InternalMessageQueue.Enqueue(packet);
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                    continue;
                }

                //DataReceived?.Invoke((IPEndPoint)any, new EventArgs());
                DataReceived?.Invoke(this,(IPEndPoint)any);
            }

            IsRunning = false;
        }

        /// <summary>
        /// 获取所有 IPv4 地址
        /// </summary>
        /// <returns></returns>
        public static IPAddress[] GetIp4Addresses()
        {
            List<IPAddress> addrs = new List<IPAddress>();
            foreach(NetworkInterface ni in GetAllPysicalAdapers())
            {
                foreach(UnicastIPAddressInformation info in  ni.GetIPProperties().UnicastAddresses)
                {
                    if(info.Address.AddressFamily==AddressFamily.InterNetwork)
                    {
                        addrs.Add(info.Address);
                    }
                }
            }
            return addrs.ToArray();
        }

        


        #region IDisposable Support
        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)。
                    FreeResources();
                }

                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
                // TODO: 将大型字段设置为 null。
                GC.SuppressFinalize(this);
                disposedValue = true;
            }
        }

        // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
        // ~UdpClientCompact() {
        //   // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
        //   Dispose(false);
        // }

        // 添加此代码以正确实现可处置模式。
        public void Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            // TODO: 如果在以上内容中替代了终结器，则取消注释以下行。
            // GC.SuppressFinalize(this);
        }
        #endregion








    }
}
